class_name BulletBatDart
extends Node2D


var sender: Node2D
var hold_item: Node2D
var attack: float = 0
var critical_rate: float = 0
var critical_bonus: float = 0
var knockback: float = 0

var shoot_dir: Vector2 = Vector2.ZERO
@export var speed: float = 500
var velocity: Vector2 = Vector2.ZERO
@export var max_shoot_time: float = 3
var max_shoot_timer: float = 0
var is_in_shoot_return: bool = false

@onready var navigation_agent_2d: NavigationAgent2D = $NavigationAgent2D
@onready var animation_player: AnimationPlayer = $AnimationPlayer

@onready var hit_area: Area2D = $HitArea
var hit_targets: Array = []

@onready var throw_audio: AudioStreamPlayer2D = $AudioStreamPlayer2D


func _ready() -> void:
	max_shoot_timer = max_shoot_time
	animation_player.play("fly")
	throw_audio.play()
	

func process_hit():
	var areas = hit_area.get_overlapping_areas()
	if areas.size() <= 0: return
	
	for area in areas:
		var source = area.source
		if not source in hit_targets:
			hit_targets.append(source)
		
			var hit_data = get_hit_data()
			source.take_hit(hit_data, sender)
	
	var level = get_tree().current_scene as Level
	level.camera.start_shake(3.0, 0.1)
	

func get_hit_data():
	var is_critical = randf() <= critical_rate
	var critical_attack = attack * (1.0 + critical_bonus)
	
	var hit_data = HitData.new()
	hit_data.is_critical = is_critical
	hit_data.attack = critical_attack if is_critical else attack
	hit_data.knockback = knockback
	
	return hit_data
	

func _physics_process(delta: float) -> void:
	process_hit()
	process_forward_move(delta)
	process_enter_shoot_return(delta)
	process_return(delta)
	
	
func process_forward_move(delta: float):
	if is_in_shoot_return: return
	
	position += shoot_dir * speed * delta
	

func process_enter_shoot_return(delta: float):
	if is_in_shoot_return: return
	
	max_shoot_timer -= delta
	if max_shoot_timer <= 0:
		max_shoot_timer = max_shoot_time
		set_shoot_return()
		

func _on_hit_area_body_entered(body: Node2D) -> void:
	if is_in_shoot_return: return
	set_shoot_return()
	

func set_shoot_return():
	is_in_shoot_return = true
	hit_targets = []
	

func process_return(delta: float):
	if not is_in_shoot_return: return
	
	if not sender or not hold_item:
		queue_free()
		return
	
	navigation_agent_2d.target_position = hold_item.shoot_start_point.global_position
		
	if navigation_agent_2d.is_navigation_finished():
		hold_item.on_bat_dart_returned()
		queue_free()
		return
	
	var next_pos = navigation_agent_2d.get_next_path_position()
	var dir = (next_pos - global_position).normalized()
	var target_velocity = dir * speed
	if navigation_agent_2d.avoidance_enabled:
		navigation_agent_2d.set_velocity(target_velocity)
	else:
		_on_navigation_agent_2d_velocity_computed(target_velocity, delta)
		
	
func _on_navigation_agent_2d_velocity_computed(safe_velocity: Vector2, delta: float = 0.0) -> void:
	velocity = velocity.lerp(safe_velocity, 0.05)
	position += velocity * delta
	
